#pragma once

#include<iostream>
#include<string>
#include<list>
#include<memory>
#include<unordered_set>
#include<mutex>
#include<algorithm>
#include "InetAddr.hpp"
#include "Log.hpp"
#include "User.hpp"

using namespace LogModule;
class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual  void SendTo(int sockfd, const std::string& message) = 0;
    virtual bool operator == (const InetAddr& u)=0;
    virtual std::string Id() = 0;
};

class User : public UserInterface
{
public:
    User(const InetAddr& id):_id(id)
    {}
    void SendTo(int sockfd, const std::string& message)
    {
        LOG(LogLevel::DEBUG)<<"send message to"<< _id.Addr()<<" info:"<<message;
        int n = ::sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());
        (void)n;
    }
    bool operator == (const InetAddr& u)
    {
        return _id == u;
    }
    std::string Id()
    {
        return _id.Addr();
    }
    ~User()
    {}
private:
    InetAddr _id;
};


//对所有用户管理起来
//观察者模式
class UserManager
{
public:
    UserManager()
    {}
    void AddUser(InetAddr& id)
    {
        std::lock_guard<std::mutex> lock(_mtx);
        for(auto& user: _online_user)
            if(*user == id)
                LOG(LogLevel::INFO)<<id.Addr()<<"用户已存在";
        LOG(LogLevel::INFO)<<"新增用户："<< id.Addr();
        _online_user.insert(std::make_shared<User>(id));
        PrintUser();
    }
    void DelUser(InetAddr& id)
    {
        // auto pos = std::remove_if(_online_user.begin(), _online_user.end(), [&id](std::shared_ptr<UserInterface>& user){
        //     return *user == id;
        // });
        //_online_user.erase(pos, _online_user.end());

        for(auto user : _online_user)
        {
            if(*user == id)
            {
                _online_user.erase(user);
                break; // 迭代器失效的问题
            }
        }
        PrintUser();
    }

    void PrintUser()
    {
        for(auto& user: _online_user)
        {
            LOG(LogLevel::DEBUG)<< "在线用户：" <<user->Id();
        }
    }
    void Router(int sockfd, const std::string& message)
    {
        for(auto& user: _online_user)
        {
            user->SendTo(sockfd, message);
        }
    }
    ~UserManager()
    {}
private:
    //std::list<std::shared_ptr<UserInterface>> _inline_user;
    std::unordered_set<std::shared_ptr<UserInterface>> _online_user;
    std::mutex _mtx;
};